#ifndef _ALGORITHM_IMPL
#define _ALGORITHM_IMPL

#include "Algorithm.h"

void mylib::get_escape_char(mylib::Buffer &in, char &c) {
		using namespace std;
		char ch; 
		if( !in.get(ch) )
			throw Err_get_ec();
		size_t len = 0;
		switch(ch) {
		case 'n' :
			c = '\n';
			break;
		case 't' :
			c = '\t';
			break;
		case 'v' :
			c = '\v';
			break;
		case 'b' :
			c = '\b';
			break;
		case 'r' :
			c = '\r';
			break;
		case 'f' :
			c = '\f';
			break;
		case 'a' :
			c = '\a';
			break;
		case '\\' :
			c = '\\';
			break;
		case '?' :
			c = '\?';
			break;
		case '\'':
			c = '\'';
			break;
		case '\"' :
			c = '\"';
			break;
		case '0' : {
			std::string s = "0";
			int i=1;
			for(; i < 3; i++ ) {
				if( !in.get(ch) )
					break;
				else if( isdigit(ch) )
					s += ch;
				else {
					in.ret();
					break;
				}
			}
			c = (char) atoi(s.c_str());
			break;		}
		case 'x' : case 'X' : {
			std::string s;
			int i=0;
			for( ; i < 2; i++ ) {
				if( !in.get(ch) )
					break;
				else if( isdigit(ch) || ( ch >= 'a' && ch <= 'f' ) || ch >= 'A' && ch <= 'F' )
					s += ch;
				else {
					in.ret();
					break;
				}
			}
			c = (char) strtol(s.c_str(), 0, 16);		//??
			break;	}
		default :
			c = ch;
			break;
		}
}
void mylib::get_str(mylib::Buffer &in, std::string &str) {
	char c;
	try {
		if( in.get(c) && c != '\"' ) {		// error
			if( !in.eof() )
				in.ret();
			throw mylib::Err_get_str();
		}
		while(in.get(c) && c != '\n' && c != '\"' ) {
			if( c == '\\' )	// escape character
				mylib::get_escape_char(in, c);		// get escape character
			str += c;
		}
		if( c == '\"' ) { 
			return;
		} else {
			if( c == '\n' )
				in.ret();
			str.clear();
			throw Err_get_str();
		}
	} catch(...) {
		throw Err_get_str();
	}
}
void mylib::get_id(mylib::Buffer &from, std::string &s){		// get a id
	skip_ws(from);
	char c;
	if( !from.get(c) )
		return;
	else if( !isalpha(c) && c!='_' ) {
		from.ret();
		return;
	} else
		s += c;
	do {
		if(from.get(c) && (isalnum(c) || c=='_') )
			s += c;
		else if( !from.eof() ) {
			from.ret();
			return;
		} else
			return;
	} while( true );
}
void mylib::skip_line_com(mylib::Buffer &from) {				// skip // comment
	char chr;
	do {
		if(!from.get(chr))		// maybe // eof
			break;
	} while( chr != '\n' );
}
void mylib::skip_dou_lines_com(mylib::Buffer &from){			// to match "*/"
	char ch;
	do {
		if( !from.get(ch) )
			throw mylib::Err_skip();
		else if( ch == '*' ) {		// the end
			char chr;
			if( !from.get(chr) )
				throw mylib::Err_skip();
			if( chr == '/' )
				break;			// get the end
			else
				from.ret();		// unget
		}
	} while(true);
}
void mylib::skip_ws(mylib::Buffer &from) {						// skip whitespace
	char c;
	while( from.get(c) && isspace(c) )
		;
	if( !from.eof() )
		from.ret();
}
#endif
